mirror of
https://git.v0id.ovh/n3wt-innov/n3wt-school.git
synced 2026-01-28 23:43:22 +00:00
refactor: adaptation mobile
This commit is contained in:
@ -12,10 +12,12 @@ import {
|
|||||||
Calendar,
|
Calendar,
|
||||||
Settings,
|
Settings,
|
||||||
FileText,
|
FileText,
|
||||||
LogOut
|
LogOut,
|
||||||
|
Menu,
|
||||||
|
X
|
||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
import DropdownMenu from '@/components/DropdownMenu';
|
import DropdownMenu from '@/components/DropdownMenu';
|
||||||
import Logo from '@/components/Logo';
|
|
||||||
import Popup from '@/components/Popup';
|
import Popup from '@/components/Popup';
|
||||||
import {
|
import {
|
||||||
FE_ADMIN_HOME_URL,
|
FE_ADMIN_HOME_URL,
|
||||||
@ -31,11 +33,13 @@ import { useSession } from 'next-auth/react';
|
|||||||
import { fetchEstablishment } from '@/app/actions/schoolAction';
|
import { fetchEstablishment } from '@/app/actions/schoolAction';
|
||||||
import ProtectedRoute from '@/components/ProtectedRoute';
|
import ProtectedRoute from '@/components/ProtectedRoute';
|
||||||
import { getGravatarUrl } from '@/utils/gravatar';
|
import { getGravatarUrl } from '@/utils/gravatar';
|
||||||
|
import Footer from '@/components/Footer';
|
||||||
|
|
||||||
export default function Layout({
|
export default function Layout({
|
||||||
children,
|
children,
|
||||||
}) {
|
}) {
|
||||||
const t = useTranslations('sidebar');
|
const t = useTranslations('sidebar');
|
||||||
|
const [isSidebarOpen, setIsSidebarOpen] = useState(false);
|
||||||
|
|
||||||
const sidebarItems = {
|
const sidebarItems = {
|
||||||
"admin": { "id": "admin", "name": t('dashboard'), "url": FE_ADMIN_HOME_URL, "icon": Home },
|
"admin": { "id": "admin", "name": t('dashboard'), "url": FE_ADMIN_HOME_URL, "icon": Home },
|
||||||
@ -50,7 +54,7 @@ export default function Layout({
|
|||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
const [isPopupVisible, setIsPopupVisible] = useState(false);
|
const [isPopupVisible, setIsPopupVisible] = useState(false);
|
||||||
const [user, setUser] = useState(null);
|
const [user, setUser] = useState(null);
|
||||||
const { data: session } = useSession();
|
const { data: session } = useSession();
|
||||||
|
|
||||||
const pathname = usePathname();
|
const pathname = usePathname();
|
||||||
const currentPage = pathname.split('/').pop();
|
const currentPage = pathname.split('/').pop();
|
||||||
@ -58,7 +62,7 @@ export default function Layout({
|
|||||||
const headerTitle = sidebarItems[currentPage]?.name || t('dashboard');
|
const headerTitle = sidebarItems[currentPage]?.name || t('dashboard');
|
||||||
|
|
||||||
const softwareName = "N3WT School";
|
const softwareName = "N3WT School";
|
||||||
const softwareVersion = `v${process.env.NEXT_PUBLIC_APP_VERSION}`;
|
const softwareVersion = `${process.env.NEXT_PUBLIC_APP_VERSION}`;
|
||||||
|
|
||||||
const handleDisconnect = () => {
|
const handleDisconnect = () => {
|
||||||
setIsPopupVisible(true);
|
setIsPopupVisible(true);
|
||||||
@ -77,6 +81,15 @@ export default function Layout({
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const toggleSidebar = () => {
|
||||||
|
setIsSidebarOpen(!isSidebarOpen);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// Fermer la sidebar quand on change de page sur mobile
|
||||||
|
setIsSidebarOpen(false);
|
||||||
|
}, [pathname]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
fetchEstablishment()
|
fetchEstablishment()
|
||||||
@ -85,7 +98,7 @@ export default function Layout({
|
|||||||
})
|
})
|
||||||
.catch(error => console.error('Error fetching establishment : ', error))
|
.catch(error => console.error('Error fetching establishment : ', error))
|
||||||
.finally(() => setIsLoading(false));
|
.finally(() => setIsLoading(false));
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchUser = async () => {
|
const fetchUser = async () => {
|
||||||
@ -99,54 +112,79 @@ export default function Layout({
|
|||||||
}, [session]);
|
}, [session]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ProtectedRoute>
|
<ProtectedRoute>
|
||||||
{!isLoading && (
|
{!isLoading && (
|
||||||
<div className="flex min-h-screen bg-gray-50">
|
<div className="flex min-h-screen bg-gray-50 relative">
|
||||||
<Sidebar establishment={establishment} currentPage={currentPage} items={Object.values(sidebarItems)} className="h-full" />
|
{/* Sidebar avec hauteur forcée */}
|
||||||
<div className="flex flex-col flex-1">
|
<div
|
||||||
{/* Header - h-16 = 64px */}
|
className={`md:block ${isSidebarOpen ? 'block' : 'hidden'} fixed md:relative inset-y-0 left-0 z-30 h-full`}
|
||||||
<header className="h-16 bg-white border-b border-gray-200 px-8 py-4 flex items-center justify-between z-9">
|
style={{ height: '100vh' }} // Force la hauteur à 100% de la hauteur de la vue
|
||||||
<div className="text-xl font-semibold">{headerTitle}</div>
|
>
|
||||||
<DropdownMenu
|
<Sidebar
|
||||||
buttonContent={
|
establishment={establishment}
|
||||||
<Image
|
currentPage={currentPage}
|
||||||
src={getGravatarUrl(user?.email)}
|
items={Object.values(sidebarItems)}
|
||||||
alt="Profile"
|
|
||||||
className="w-8 h-8 rounded-full cursor-pointer"
|
onCloseMobile={toggleSidebar}
|
||||||
width={32}
|
|
||||||
height={32}
|
/>
|
||||||
/>
|
</div>
|
||||||
}
|
|
||||||
items={dropdownItems}
|
{/* Overlay pour fermer la sidebar en cliquant à l'extérieur sur mobile */}
|
||||||
buttonClassName=""
|
{isSidebarOpen && (
|
||||||
menuClassName="absolute right-0 mt-2 w-48 bg-white border border-gray-200 rounded shadow-lg"
|
<div
|
||||||
/>
|
className="fixed inset-0 bg-black bg-opacity-50 z-20 md:hidden"
|
||||||
</header>
|
onClick={toggleSidebar}
|
||||||
{/* Main Content */}
|
/>
|
||||||
<div className="flex-1 flex flex-col">
|
)}
|
||||||
{/* Content avec scroll si nécessaire */}
|
|
||||||
<div className="flex-1 overflow-auto">
|
<div className="flex-1 flex flex-col">
|
||||||
{children}
|
{/* Header responsive */}
|
||||||
</div>
|
<header className="h-16 bg-white border-b border-gray-200 px-4 md:px-8 py-4 flex items-center justify-between z-10">
|
||||||
{/* Footer - h-16 = 64px */}
|
<div className="flex items-center">
|
||||||
<footer className="h-16 bg-white border-t border-gray-200 px-8 py-4 flex items-center justify-between">
|
<button
|
||||||
<div className="text-sm font-light">
|
className="mr-4 md:hidden text-gray-600 hover:text-gray-900"
|
||||||
<span>© {new Date().getFullYear()} N3WT-INNOV Tous droits réservés.</span>
|
onClick={toggleSidebar}
|
||||||
<div className="text-sm font-light">{softwareName} - {softwareVersion}</div>
|
aria-label="Toggle menu"
|
||||||
</div>
|
>
|
||||||
<Logo className="w-8 h-8" />
|
{isSidebarOpen ? <X size={24} /> : <Menu size={24} />}
|
||||||
</footer>
|
</button>
|
||||||
|
<div className="text-lg md:text-xl font-semibold">{headerTitle}</div>
|
||||||
</div>
|
</div>
|
||||||
|
<DropdownMenu
|
||||||
|
buttonContent={
|
||||||
|
<Image
|
||||||
|
src={getGravatarUrl(user?.email)}
|
||||||
|
alt="Profile"
|
||||||
|
className="w-8 h-8 rounded-full cursor-pointer"
|
||||||
|
width={32}
|
||||||
|
height={32}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
items={dropdownItems}
|
||||||
|
buttonClassName=""
|
||||||
|
menuClassName="absolute right-0 mt-2 w-48 bg-white border border-gray-200 rounded shadow-lg"
|
||||||
|
/>
|
||||||
|
</header>
|
||||||
|
{/* Main Content */}
|
||||||
|
<div className="flex-1 flex flex-col">
|
||||||
|
{/* Content avec scroll si nécessaire */}
|
||||||
|
<div className="flex-1 overflow-auto p-4 md:p-6">
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
{/* Footer responsive */}
|
||||||
|
<Footer softwareName={softwareName} softwareVersion={softwareVersion} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
</div>
|
||||||
<Popup
|
)}
|
||||||
visible={isPopupVisible}
|
<Popup
|
||||||
message="Êtes-vous sûr(e) de vouloir vous déconnecter ?"
|
visible={isPopupVisible}
|
||||||
onConfirm={confirmDisconnect}
|
message="Êtes-vous sûr(e) de vouloir vous déconnecter ?"
|
||||||
onCancel={() => setIsPopupVisible(false)}
|
onConfirm={confirmDisconnect}
|
||||||
/>
|
onCancel={() => setIsPopupVisible(false)}
|
||||||
</ProtectedRoute>
|
/>
|
||||||
|
</ProtectedRoute>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -66,48 +66,45 @@ export default function Layout({
|
|||||||
<ProtectedRoute>
|
<ProtectedRoute>
|
||||||
<div className="flex flex-col min-h-screen bg-gray-50">
|
<div className="flex flex-col min-h-screen bg-gray-50">
|
||||||
{/* Entête */}
|
{/* Entête */}
|
||||||
<header className="bg-white border-b border-gray-200 px-8 py-4 flex items-center justify-between fixed top-0 left-0 right-0 z-10">
|
<header className="bg-white border-b border-gray-200 px-4 py-2 md:px-8 md:py-4 flex items-center justify-between fixed top-0 left-0 right-0 z-10">
|
||||||
<div className="flex items-center space-x-2">
|
<div className="flex items-center space-x-2">
|
||||||
<Logo className="h-8 w-8" /> {/* Utilisation du composant Logo */}
|
<Logo className="h-6 w-6 md:h-8 md:w-8" /> {/* Utilisation du composant Logo */}
|
||||||
|
|
||||||
<div className="text-xl font-semibold">Accueil</div>
|
<div className="text-lg md:text-xl font-semibold">Accueil</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center space-x-4">
|
<div className="flex items-center space-x-2 md:space-x-4">
|
||||||
<button
|
<button
|
||||||
className="p-2 rounded-full hover:bg-gray-200"
|
className="p-1 md:p-2 rounded-full hover:bg-gray-200"
|
||||||
onClick={() => { router.push(FE_PARENTS_HOME_URL); }} // Utilisation de router pour revenir à l'accueil parent
|
onClick={() => { router.push(FE_PARENTS_HOME_URL); }} // Utilisation de router pour revenir à l'accueil parent
|
||||||
>
|
>
|
||||||
<Home />
|
<Home className="h-5 w-5 md:h-6 md:w-6" />
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
<button
|
<button
|
||||||
className="p-2 rounded-full hover:bg-gray-200"
|
className="p-1 md:p-2 rounded-full hover:bg-gray-200"
|
||||||
onClick={() => { router.push(FE_PARENTS_MESSAGERIE_URL); }} // Utilisation de router
|
onClick={() => { router.push(FE_PARENTS_MESSAGERIE_URL); }} // Utilisation de router
|
||||||
>
|
>
|
||||||
<MessageSquare />
|
<MessageSquare className="h-5 w-5 md:h-6 md:w-6" />
|
||||||
|
|
||||||
</button>
|
</button>
|
||||||
{messages.length > 0 && (
|
{messages.length > 0 && (
|
||||||
<span className="absolute top-0 right-0 block h-2 w-2 rounded-full bg-emerald-600"></span>
|
<span className="absolute top-0 right-0 block h-2 w-2 rounded-full bg-emerald-600"></span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<DropdownMenu
|
<DropdownMenu
|
||||||
buttonContent={<User />}
|
buttonContent={<User className="h-5 w-5 md:h-6 md:w-6" />}
|
||||||
items={[
|
items={[
|
||||||
{ label: 'Se déconnecter', icon: LogOut, onClick: handleDisconnect },
|
{ label: 'Se déconnecter', icon: LogOut, onClick: handleDisconnect },
|
||||||
{ label: 'Settings', icon: Settings , onClick: () => { router.push(FE_PARENTS_SETTINGS_URL); } }
|
{ label: 'Settings', icon: Settings , onClick: () => { router.push(FE_PARENTS_SETTINGS_URL); } }
|
||||||
]}
|
]}
|
||||||
buttonClassName="p-2 rounded-full hover:bg-gray-200"
|
buttonClassName="p-1 md:p-2 rounded-full hover:bg-gray-200"
|
||||||
menuClassName="absolute right-0 mt-2 w-48 bg-white border border-gray-200 rounded-md shadow-lg"
|
menuClassName="absolute right-0 mt-2 w-36 md:w-48 bg-white border border-gray-200 rounded-md shadow-lg"
|
||||||
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
{/* Content */}
|
{/* Content */}
|
||||||
<div className="pt-20 p-8 flex-1"> {/* Ajout de flex-1 pour utiliser toute la hauteur disponible */}
|
<div className="pt-16 md:pt-20 p-4 md:p-8 flex-1"> {/* Ajout de flex-1 pour utiliser toute la hauteur disponible */}
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -2,8 +2,8 @@
|
|||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
import Table from '@/components/Table';
|
import Table from '@/components/Table';
|
||||||
import { Edit } from 'lucide-react';
|
import { Edit, Users } from 'lucide-react';
|
||||||
import StatusLabel from '@/components/StatusLabel';
|
import StatusLabel from '@/components/StatusLabel';
|
||||||
import { FE_PARENTS_EDIT_INSCRIPTION_URL } from '@/utils/Url';
|
import { FE_PARENTS_EDIT_INSCRIPTION_URL } from '@/utils/Url';
|
||||||
import { fetchChildren } from '@/app/actions/subscriptionAction';
|
import { fetchChildren } from '@/app/actions/subscriptionAction';
|
||||||
import logger from '@/utils/logger';
|
import logger from '@/utils/logger';
|
||||||
@ -11,10 +11,11 @@ import { useSession } from 'next-auth/react';
|
|||||||
import { FE_USERS_LOGIN_URL } from '@/utils/Url';
|
import { FE_USERS_LOGIN_URL } from '@/utils/Url';
|
||||||
|
|
||||||
export default function ParentHomePage() {
|
export default function ParentHomePage() {
|
||||||
const [actions, setActions] = useState([]);
|
|
||||||
const [children, setChildren] = useState([]);
|
const [children, setChildren] = useState([]);
|
||||||
const { data: session, status } = useSession();
|
const { data: session, status } = useSession();
|
||||||
const [userId, setUserId] = useState(null);
|
const [userId, setUserId] = useState(null);
|
||||||
|
const [currentPage, setCurrentPage] = useState(1);
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
@ -61,29 +62,62 @@ export default function ParentHomePage() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
// Définir les colonnes du tableau
|
||||||
<div>
|
const childrenColumns = [
|
||||||
<div>
|
{ name: 'Nom', transform: (row) => `${row.student.last_name} ${row.student.first_name}` },
|
||||||
<h2 className="text-xl font-semibold mb-4">Dernières actions à effectuer</h2>
|
{
|
||||||
<Table data={actions} columns={actionColumns} itemsPerPage={5} />
|
name: 'Statut',
|
||||||
</div>
|
transform: (row) => (
|
||||||
|
<div className="flex justify-center items-center">
|
||||||
|
<StatusLabel status={row.status} showDropdown={false}/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Actions',
|
||||||
|
transform: (row) => (
|
||||||
|
<div className="flex justify-center">
|
||||||
|
<button
|
||||||
|
className="p-2 hover:bg-gray-100 rounded-full transition-colors"
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
handleEdit(row.student.id);
|
||||||
|
}}
|
||||||
|
aria-label="Modifier"
|
||||||
|
>
|
||||||
|
<Edit className="h-5 w-5" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const itemsPerPage = 5;
|
||||||
|
const totalPages = Math.ceil(children.length / itemsPerPage) || 1;
|
||||||
|
|
||||||
|
const handlePageChange = (newPage) => {
|
||||||
|
setCurrentPage(newPage);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="px-2 py-4 md:px-4 max-w-full">
|
||||||
<div>
|
<div>
|
||||||
<h2 className="text-xl font-semibold mb-4">Enfants</h2>
|
<h2 className="text-xl font-semibold mb-3 px-1 flex items-center gap-2">
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
<Users className="h-6 w-6 text-emerald-600" />
|
||||||
{children.map((child) => (
|
Enfants
|
||||||
<div key={child.student.id} className={`border p-4 rounded shadow ${getShadowColor(child.status)}`}>
|
</h2>
|
||||||
<div className="flex justify-between items-center">
|
<div className="overflow-x-auto">
|
||||||
<h3 className="text-lg font-semibold">{child.student.last_name} {child.student.first_name}</h3>
|
<Table
|
||||||
<Edit className="cursor-pointer" onClick={() => handleEdit(child.student.id)} />
|
data={children}
|
||||||
</div>
|
columns={childrenColumns}
|
||||||
<StatusLabel status={child.status } showDropdown={false}/>
|
itemsPerPage={itemsPerPage}
|
||||||
</div>
|
currentPage={currentPage}
|
||||||
))}
|
totalPages={totalPages}
|
||||||
|
onPageChange={handlePageChange}
|
||||||
|
defaultTheme="bg-gray-50"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
17
Front-End/src/components/Footer.js
Normal file
17
Front-End/src/components/Footer.js
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import Logo from '@/components/Logo';
|
||||||
|
|
||||||
|
export default function Footer ({softwareName, softwareVersion}) {
|
||||||
|
|
||||||
|
return (
|
||||||
|
<footer className="h-16 bg-white border-t border-gray-200 px-8 py-4 flex items-center justify-between">
|
||||||
|
<div className="text-sm font-light">
|
||||||
|
<span>© {new Date().getFullYear()} N3WT-INNOV Tous droits réservés.</span>
|
||||||
|
</div>
|
||||||
|
<div className="text-sm font-light flex items-center justify-between">
|
||||||
|
<div className="text-sm font-light mr-4">{softwareName} - {softwareVersion}</div>
|
||||||
|
<Logo className="w-8 h-8" />
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
@ -29,7 +29,7 @@ function Sidebar({ establishment, currentPage, items }) {
|
|||||||
|
|
||||||
return <>
|
return <>
|
||||||
{/* Sidebar */}
|
{/* Sidebar */}
|
||||||
<div className="w-64 bg-white border-r border-gray-200 py-6 px-4">
|
<div className="w-64 bg-white border-r h-full border-gray-200 py-6 px-4">
|
||||||
<div className="flex items-center mb-8 px-2">
|
<div className="flex items-center mb-8 px-2">
|
||||||
<div className="text-xl font-semibold">{establishment?.name}</div>
|
<div className="text-xl font-semibold">{establishment?.name}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
62
README.md
62
README.md
@ -0,0 +1,62 @@
|
|||||||
|
# N3wt School
|
||||||
|
|
||||||
|
Logiciel de gestion d'école
|
||||||
|
|
||||||
|
|
||||||
|
## Maquette
|
||||||
|
|
||||||
|
Maquette figma : https://www.figma.com/design/1BtWHIQlJDTeue2oYblefV/Maquette-Logiciel-de-gestion-Ecole?node-id=42-296&t=AdaSQYWkLLf1o5OI-0
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
### Installation de docker
|
||||||
|
Lien de téléchargement : https://www.docker.com/get-started/
|
||||||
|
|
||||||
|
# Lancement de monteschool
|
||||||
|
|
||||||
|
```sh
|
||||||
|
docker compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
Lancement du front end
|
||||||
|
```sh
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
se connecter à localhost:8080
|
||||||
|
|
||||||
|
# Installation et développement en local
|
||||||
|
|
||||||
|
* [Installation Manuelle](./docs/Installation_Manuelle.md)
|
||||||
|
* [Convention de codage](./docs/CODING_GUIDELINES.md)
|
||||||
|
|
||||||
|
# Installer la vérification de commit (dans le projet principal)
|
||||||
|
|
||||||
|
```
|
||||||
|
npm i
|
||||||
|
npm run prepare
|
||||||
|
```
|
||||||
|
|
||||||
|
# Faire une livraison Mise en Production
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# Faire la première release (1.0.0)
|
||||||
|
npm run release -- --first-release
|
||||||
|
|
||||||
|
# Faire une prerelease (RC,alpha,beta)
|
||||||
|
npm run release -- --prerelease <name>
|
||||||
|
|
||||||
|
|
||||||
|
# Faire une release
|
||||||
|
npm run release
|
||||||
|
|
||||||
|
# Forcer la release sur un mode particulier (majeur, mineur ou patch)
|
||||||
|
# npm run script
|
||||||
|
npm run release -- --release-as minor
|
||||||
|
# Or
|
||||||
|
npm run release -- --release-as 1.1.0
|
||||||
|
|
||||||
|
# ignorer les hooks de commit lors de la release
|
||||||
|
npm run release -- --no-verify
|
||||||
|
```
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user