Skip to content

Commit

Permalink
Merge branch 'main' into 3583-update-convocation-template
Browse files Browse the repository at this point in the history
  • Loading branch information
nicobret authored Nov 18, 2024
2 parents 475634c + a91f535 commit 62c5fd8
Show file tree
Hide file tree
Showing 212 changed files with 16,296 additions and 4,722 deletions.
1 change: 1 addition & 0 deletions .github/workflows/deploy-custom-env.yml
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ jobs:
image_name: ${{matrix.app.name}}
dockerfile_path: ${{matrix.app.path}}/Dockerfile
image_tag: ${{matrix.app.tag}}
image_tag_stable: "custom-latest"
sentry_auth_token: ${{ secrets.SENTRY_AUTH_TOKEN }}

deploy:
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/run-tests-api-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ jobs:
id: cache-npm
with:
path: |
apiv2/node_modules
node_modules
api/node_modules
app/node_modules
Expand Down
56 changes: 56 additions & 0 deletions .github/workflows/run-tests-api-v2.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
name: API V2 - Run Tests

on:
workflow_dispatch:
workflow_call:
inputs:
branch_name:
required: true
type: string
pull_request:
branches:
- main
merge_group:
types:
- checks_requested

jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Git checkout
uses: actions/checkout@v4
with:
ref: ${{ inputs.branch_name }}

- name: Node 18.x
uses: actions/setup-node@v4
with:
node-version: 18.x

- uses: actions/cache@v4
id: cache-npm
with:
path: |
apiv2/node_modules
node_modules
api/node_modules
app/node_modules
admin/node_modules
packages/ds/node_modules
packages/lib/node_modules
key: ${{ runner.os }}-nodemodules-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-nodemodules-
- name: Install packages
if: steps.cache-npm.outputs.cache-hit != 'true'
run: npm ci

- name: Build lib
working-directory: packages/lib
run: npm run build

- name: Run tests
working-directory: apiv2
run: npm test
1 change: 1 addition & 0 deletions .github/workflows/run-tests-api.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ jobs:
id: cache-npm
with:
path: |
apiv2/node_modules
node_modules
api/node_modules
app/node_modules
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/run-tests-front.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ jobs:
id: cache-npm
with:
path: |
apiv2/node_modules
node_modules
api/node_modules
app/node_modules
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/run-tests-lib.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ jobs:
id: cache-npm
with:
path: |
apiv2/node_modules
node_modules
api/node_modules
app/node_modules
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

.vscode/*
!.vscode/tasks.json
!.vscode/settings.json
.env*
.cache_ggshield
Zammadwebhook.json
Expand Down
23 changes: 23 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"jest.shell": "/bin/zsh",
"jest.virtualFolders": [
{
"name": "snu-api-v2",
"rootPath": "apiv2",
"jestCommandLine": "source ~/.zshrc && nvm use && npm run test --",
"runMode": "on-demand"
},
{
"name": "snu-api-v1",
"rootPath": "api",
"jestCommandLine": "source ~/.zshrc && nvm use && npm run test --",
"runMode": "on-demand"
},
{
"name": "snu-lib",
"rootPath": "packages/lib",
"jestCommandLine": "source ~/.zshrc && nvm use && npm run test --",
"runMode": "watch"
}
]
}
2 changes: 1 addition & 1 deletion admin/src/components/Loader.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from "react";
import ReactLoading from "react-loading";
import styled from "styled-components";

export default function Loader({ type = "spin", size = "3rem", color = "#5245cc", className = "", containerClassName = "" }) {
export default function Loader({ type = "spin", size = "3rem", color = "#2563eb", className = "", containerClassName = "" }) {
return (
<Container className={containerClassName}>
<ReactLoading type={type} color={color} width={size} height={size} className={className} />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,26 @@
import React from "react";
import React, { ReactElement } from "react";
import ChevronDown from "../assets/icons/ChevronDown";

type OptionGroupItem = {
key: string;
render: React.ReactNode;
};

interface SelectActionProps {
optionsGroup: Array<{
key: string;
title: string | React.ReactNode;
items: Array<OptionGroupItem>;
}>;
title: string;
Icon?: ReactElement;
disabled?: boolean;
alignItems?: "left" | "center" | "right";
buttonClassNames?: string;
textClassNames?: string;
rightIconClassNames?: string;
}

export default function SelectAction({
optionsGroup,
title,
Expand All @@ -10,11 +30,11 @@ export default function SelectAction({
buttonClassNames = "border-[1px] border-gray-300",
textClassNames = "text-gray-700 font-medium text-sm",
rightIconClassNames = "text-gray-400",
}) {
}: SelectActionProps) {
const [open, setOpen] = React.useState(false);
const [loading, setLoading] = React.useState(false);
const [loadingLabel, setLoadingLabel] = React.useState("Chargement...");
const ref = React.useRef(null);
const ref = React.useRef<HTMLDivElement>(null);

const onClickItem = async (item) => {
setLoading(true);
Expand Down
42 changes: 32 additions & 10 deletions admin/src/components/UserCard.jsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,53 @@
import React from "react";
import { ROLES, translate } from "snu-lib";
import cx from "classnames";

export default function UserCard({ user }) {
function getAvatar(user) {
if (!user) return "??";
if (user?.firstName === "Acteur inconnu") return "?";
if (user?.firstName && user?.lastName) return `${user?.firstName?.substring(0, 1)}${user?.lastName ? user.lastName.substring(0, 1) : null}`;
return "🤖";
// return "?";
if (user?.firstName && !user?.lastname) return "🤖";
}
function getlink(user) {
function getLink(user) {
if (Object.values(ROLES).includes(user?.role)) return `/user/${user._id}`;
if (user?.role === "Volontaire") return `/volontaire/${user._id}`;
return null;
}
function getRole(user) {
if (!user) return "Donnée indisponible";
if (user.role) {
return translate(user.role);
} else {
return "Script";
}
}
function getAuthor(user) {
if (!user) return "Auteur inconnu";
if (user.firstName && user.lastName) return `${user.firstName} ${user.lastName.toUpperCase()}`;
if (user.firstName && !user.lastName) return user.firstName;
}

if (!user) return null;
return (
<a href={getlink(user)} className=" group flex w-full flex-col hover:cursor-pointer">
<a
href={getLink(user)}
target="_blank"
rel="noreferrer"
className={cx("group flex w-full flex-col", {
"hover:cursor-pointer hover:text-blue-600": getLink(user) !== null,
"hover:text-inherit": getLink(user) === null,
})}>
<div className="flex items-center gap-2">
<div className="flex h-10 w-10 shrink-0 items-center justify-center rounded-full border-2 border-white bg-slate-100 font-medium uppercase text-blue-600 transition group-hover:bg-blue-600 group-hover:text-slate-100">
<div
className={cx("flex h-10 w-10 shrink-0 items-center justify-center rounded-full border-2 border-white bg-slate-100 font-medium uppercase ", {
"text-blue-600 transition group-hover:bg-blue-600 group-hover:text-slate-100": getLink(user) !== null,
"text-cyan-900": getLink(user) === null,
})}>
{getAvatar(user)}
</div>
<div className="flex w-10/12 flex-col leading-5">
<p className="w-full truncate font-medium decoration-2 underline-offset-2">
{user.firstName} {user.lastName && user.lastName}
</p>
<p className="w-full truncate capitalize text-gray-400 decoration-2 underline-offset-2">{translate(user?.role)}</p>
<p className="w-full truncate font-medium decoration-2 underline-offset-2 text-sm">{getAuthor(user)}</p>
<p className="w-full truncate capitalize text-gray-500 text-xs decoration-2 underline-offset-2">{getRole(user)}</p>
</div>
</div>
</a>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,41 @@ function classNames(...classes) {
return classes.filter(Boolean).join(" ");
}

export interface Filter {
title?: string;
name?: string;
missingLabel?: string;
translate?: (item: any) => any;
filter?: any[];
// custom ?
parentGroup?: string;
customComponent?: any;
defaultValue?: string | string[];
isSingle?: boolean;
reduce?: (value: any[]) => any[];
sort?: (value: any[]) => any[];
getQuery?: (value: any) => any;
allowEmpty?: boolean;
disabledBaseQuery?: boolean;
options?: any;
}

interface FiltersProps {
route: string;
pageId: string;
filters: Filter[];
searchPlaceholder?: string;
setData: (data: any) => void;
selectedFilters: { [key: string]: Filter };
setSelectedFilters: (filters: { [key: string]: Filter }) => void;
paramData: any;
setParamData: (data: any) => void;
defaultUrlParam?: any;
size?: any;
intermediateFilters?: any[];
disabled?: boolean;
}

export default function Filters({
route,
pageId,
Expand All @@ -30,25 +65,25 @@ export default function Filters({
size,
intermediateFilters = [],
disabled = false,
}) {
}: FiltersProps) {
const [search, setSearch] = useState("");
const [dataFilter, setDataFilter] = useState({});
const [filtersVisible, setFiltersVisible] = useState(filters);
const [categories, setCategories] = useState([]);
const [categories, setCategories] = useState<string[]>([]);
const [savedView, setSavedView] = useState([]);
const [firstLoad, setFirstLoad] = useState(true);
const [isShowing, setIsShowing] = useState(false);
const [isShowing, setIsShowing] = useState<string | boolean>(false);

const location = useLocation();
const history = useHistory();

const ref = useRef(null);
const refFilter = useRef(null);
const ref = useRef<HTMLButtonElement>(null);
const refFilter = useRef<HTMLDivElement>(null);

const hasSomeFilterSelected =
selectedFilters &&
Object.keys(selectedFilters).find(
(key) => selectedFilters[key]?.filter?.length > 0 && selectedFilters[key]?.filter[0]?.toString().trim() !== "" && filters.find((f) => f.name === key),
(key) => selectedFilters[key]?.filter?.length && selectedFilters[key]?.filter?.[0]?.toString().trim() !== "" && filters.find((f) => f.name === key),
);

// Initialization
Expand Down Expand Up @@ -87,10 +122,10 @@ export default function Filters({
setCategories([]);
return;
}
const newCategories = [];
const newCategories: string[] = [];
filtersVisible?.forEach((f) => {
if (!newCategories.includes(f.parentGroup)) {
newCategories.push(f.parentGroup);
if (!newCategories.includes(f.parentGroup!)) {
newCategories.push(f.parentGroup!);
}
});
setCategories(newCategories);
Expand All @@ -103,7 +138,11 @@ export default function Filters({
buildQuery(route, selectedFilters, paramData?.page, filters, paramData?.sort, size).then((res) => {
if (!res) return;
setDataFilter({ ...dataFilter, ...res.newFilters });
const newParamData = {
const newParamData: {
count: number;
filters: { [key: string]: Filter };
page?: number;
} = {
count: res.count,
filters: { ...dataFilter, ...res.newFilters },
};
Expand All @@ -130,9 +169,9 @@ export default function Filters({
const newFilters = {};
filters.map((f) => {
if (f?.customComponent?.getQuery) {
newFilters[f.name] = { filter: f.defaultValue, customComponentQuery: f.getQuery(f.defaultValue) };
newFilters[f?.name || ""] = { filter: f.defaultValue, customComponentQuery: f.getQuery?.(f.defaultValue) };
} else {
newFilters[f.name] = { filter: f?.defaultValue ? f.defaultValue : [] };
newFilters[f?.name || ""] = { filter: f?.defaultValue ? f.defaultValue : [] };
}
});
return newFilters;
Expand Down Expand Up @@ -182,7 +221,7 @@ export default function Filters({
<input
name={"searchbar"}
placeholder={searchPlaceholder}
value={selectedFilters?.searchbar?.filter[0] || ""}
value={selectedFilters?.searchbar?.filter?.[0] || ""}
onChange={(e) => {
setSelectedFilters({ ...selectedFilters, [e.target.name]: { filter: [e.target.value] } });
}}
Expand Down Expand Up @@ -249,6 +288,7 @@ export default function Filters({
allowEmpty: false,
customComponent: (setFilter, filter) => (
<IntermediateFilter
// @ts-expect-error
selectedFilters={selectedFilters}
setSelectedFilters={setSelectedFilters}
setParamData={setParamData}
Expand All @@ -262,10 +302,12 @@ export default function Filters({
return (
<FilterPopOver
key={item.title}
// @ts-expect-error
filter={customItem}
// @ts-expect-error
selectedFilters={selectedFilters}
setSelectedFilters={setSelectedFilters}
data={item?.disabledBaseQuery ? item.options : dataFilter[item?.name] || []}
data={item?.disabledBaseQuery ? item.options : dataFilter[item?.name || ""] || []}
isShowing={isShowing === item.name}
setIsShowing={(value) => setIsShowing(value)}
setParamData={setParamData}
Expand Down
Loading

0 comments on commit 62c5fd8

Please sign in to comment.