Merge pull request #105 from learnhouse/swve/eng-84-set-confirmation-screens

Set confirmation screens for delete actions
This commit is contained in:
Badr B 2023-07-26 21:04:51 +02:00 committed by GitHub
commit 5f28420040
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 227 additions and 79 deletions

View file

@ -2,6 +2,7 @@
import AuthenticatedClientElement from '@components/Security/AuthenticatedClientElement';
import { AuthContext } from '@components/Security/AuthProvider';
import ConfirmationModal from '@components/StyledElements/ConfirmationModal/ConfirmationModal';
import { getUriWithOrg } from '@services/config/config';
import { deleteCollection } from '@services/courses/collections';
import { revalidateTags } from '@services/utils/ts/requests';
@ -26,9 +27,17 @@ const CollectionAdminEditsArea = (props: any) => {
return (
<AuthenticatedClientElement orgId={props.org_id} checkMethod='roles'>
<div className="flex space-x-2 py-2">
<button className="rounded-md text-sm px-3 font-bold text-red-800 bg-red-200 w-16 flex justify-center items-center" onClick={() => deleteCollectionUI(props.collection_id)}>
Delete <Trash size={10}></Trash>
</button>
<ConfirmationModal
confirmationMessage="Are you sure you want to delete this collection?"
confirmationButtonText="Delete Collection"
dialogTitle={"Delete " + props.collection.name + " ?"}
dialogTrigger={
<button className="rounded-md text-sm px-3 font-bold text-red-800 bg-red-200 w-16 flex justify-center items-center" >
Delete <Trash size={10}></Trash>
</button>}
functionToExecute={() => deleteCollectionUI(props.collection_id)}
status='warning'
></ConfirmationModal>
</div>
</AuthenticatedClientElement>
)

View file

@ -16,6 +16,7 @@ import GeneralWrapperStyled from '@components/StyledElements/Wrappers/GeneralWra
import TypeOfContentTitle from '@components/StyledElements/Titles/TypeOfContentTitle';
import AuthenticatedClientElement from '@components/Security/AuthenticatedClientElement';
import { getCourseThumbnailMediaDirectory } from '@services/media/media';
import ConfirmationModal from '@components/StyledElements/ConfirmationModal/ConfirmationModal';
interface CourseProps {
orgslug: string;
@ -48,6 +49,7 @@ function Courses(props: CourseProps) {
return (
<div>
<GeneralWrapperStyled>
<div className='flex flex-wrap justify-between'>
<TypeOfContentTitle title="Courses" type="cou" />
<AuthenticatedClientElement checkMethod='roles' orgId={props.org_id}>
@ -73,7 +75,7 @@ function Courses(props: CourseProps) {
<div className="flex flex-wrap">
{courses.map((course: any) => (
<div className="px-3" key={course.course_id}>
<AdminEditsArea course={course} orgSlug={orgslug} courseId={course.course_id} deleteCourses={deleteCourses} />
<AdminEditsArea course={course} orgSlug={orgslug} courseId={course.course_id} deleteCourses={deleteCourses} />
<Link href={getUriWithOrg(orgslug, "/course/" + removeCoursePrefix(course.course_id))}>
<div className="inset-0 ring-1 ring-inset ring-black/10 rounded-lg shadow-xl relative w-[249px] h-[131px] bg-cover" style={{ backgroundImage: `url(${getCourseThumbnailMediaDirectory(course.org_id, course.course_id, course.thumbnail)})` }}>
@ -94,9 +96,17 @@ function Courses(props: CourseProps) {
const AdminEditsArea = (props: { orgSlug: string, courseId: string, course: any, deleteCourses: any }) => {
return (
<AuthenticatedClientElement checkMethod='roles' orgId={props.course.org_id}><div className="flex space-x-2 py-2">
<button className="rounded-md text-sm px-3 font-bold text-red-800 bg-red-200 w-16 flex justify-center items-center" onClick={() => props.deleteCourses(props.courseId)}>
Delete <Trash size={10}></Trash>
</button>
<ConfirmationModal
confirmationButtonText='Delete Course'
confirmationMessage='Are you sure you want to delete this course?'
dialogTitle={'Delete ' + props.course.name + ' ?'}
dialogTrigger={
<button className="rounded-md text-sm px-3 font-bold text-red-800 bg-red-200 w-16 flex justify-center items-center" >
Delete <Trash size={10}></Trash>
</button>}
functionToExecute={() => props.deleteCourses(props.courseId)}
status='warning'
></ConfirmationModal>
<Link href={getUriWithOrg(props.orgSlug, "/course/" + removeCoursePrefix(props.courseId) + "/edit")}>
<button className="rounded-md text-sm px-3 font-bold text-orange-800 bg-orange-200 w-16 flex justify-center items-center">
Edit <Edit2 size={10}></Edit2>

View file

@ -64,7 +64,7 @@ const OrgHomePage = async (params: any) => {
<div className="flex -space-x-4">
{collection.courses.slice(0, 3).map((course: any) => (
<Link key={course.course_id} href={getUriWithOrg(orgslug, "/course/" + course.course_id.substring(7))}>
<img className="w-12 h-12 rounded-full flex items-center justify-center shadow-lg ring-2 ring-white z-50" key={course.course_id} src={`url(${getCourseThumbnailMediaDirectory(course.org_id, course.course_id, course.thumbnail)})`} alt={course.name} />
<img className="w-12 h-12 rounded-full flex items-center justify-center shadow-lg ring-2 ring-white z-50" key={course.course_id} src={`${getCourseThumbnailMediaDirectory(course.org_id, course.course_id, course.thumbnail)}`} alt={course.name} />
</Link>
))}
</div>

View file

@ -3,6 +3,7 @@ import styled from "styled-components";
import { DragDropContext, Droppable, Draggable } from "react-beautiful-dnd";
import Activity from "./Activity";
import { PlusSquare, Trash, Trash2 } from "lucide-react";
import ConfirmationModal from "@components/StyledElements/ConfirmationModal/ConfirmationModal";
function Chapter(props: any) {
return (
@ -19,16 +20,18 @@ function Chapter(props: any) {
<h3 className="flex space-x-2 pt-3 font-bold text-md items-center">
<p>{props.info.list.chapter.name}
</p>
<ConfirmationModal
confirmationButtonText="Delete Chapter"
confirmationMessage="Are you sure you want to delete this chapter?"
dialogTitle={"Delete " + props.info.list.chapter.name + " ?"}
dialogTrigger={
<button className="rounded-md text-sm px-3 font-bold text-red-800 bg-red-200 w-16 flex justify-center items-center" >
Delete <Trash size={10}></Trash>
</button>}
functionToExecute={() => props.deleteChapter(props.info.list.chapter.id)}
status='warning'
></ConfirmationModal>
<div
className="hover:cursor-pointer p-1 rounded-md bg-slate-100"
onClick={() => {
props.deleteChapter(props.info.list.chapter.id);
}}
>
<Trash2 className="text-slate-500" size={16} />
</div>
</h3>
<Droppable key={props.info.list.chapter.id} droppableId={props.info.list.chapter.id} type="activity">
{(provided) => (
@ -68,8 +71,6 @@ const ChapterWrapper = styled.div`
border: 1px solid rgba(255, 255, 255, 0.19);
box-shadow: 0px 13px 33px -13px rgb(0 0 0 / 12%);
transition: all 0.2s ease;
h3{
padding-left: 20px;
padding-right: 20px;

View file

@ -0,0 +1,128 @@
'use client';
import React from 'react';
import * as Dialog from '@radix-ui/react-dialog';
import { styled, keyframes } from '@stitches/react';
import { blackA, } from '@radix-ui/colors';
import { AlertTriangle, Info } from 'lucide-react';
type ModalParams = {
confirmationMessage: string;
confirmationButtonText: string;
dialogTitle: string;
functionToExecute: any;
dialogTrigger?: React.ReactNode;
status?: "warning" | "info";
};
const ConfirmationModal = (params: ModalParams) => {
const [isDialogOpen, setIsDialogOpen] = React.useState(false);
const warningColors = 'bg-red-100 text-red-600'
const infoColors = 'bg-blue-100 text-blue-600'
const warningButtonColors = 'text-white bg-red-500 hover:bg-red-600'
const infoButtonColors = 'text-white bg-blue-500 hover:bg-blue-600'
const onOpenChange = React.useCallback(
(open: any) => {
setIsDialogOpen(open);
},
[setIsDialogOpen]
);
return (
<Dialog.Root open={isDialogOpen} onOpenChange={onOpenChange}>
{params.dialogTrigger ? (
<Dialog.Trigger asChild >
{params.dialogTrigger}
</Dialog.Trigger>
) : null}
<Dialog.Portal>
<DialogOverlay />
<DialogContent >
<div className='h-26 flex space-x-4 tracking-tight'>
<div className={`icon p-6 rounded-xl flex items-center align-content-center ${params.status === 'warning' ? warningColors : infoColors}`}>
{params.status === 'warning' ? <AlertTriangle size={35} /> : <Info size={35} />}
</div>
<div className="text pt-1 space-x-0 w-auto flex-grow">
<div className="text-xl font-bold text-black ">
{params.dialogTitle}
</div>
<div className="text-md text-gray-500 w-60 leading-tight">
{params.confirmationMessage}
</div>
<div className="flex flex-row-reverse pt-2">
<div className={`rounded-md text-sm px-3 py-2 font-bold flex justify-center items-center hover:cursor-pointer ${params.status === 'warning' ? warningButtonColors : infoButtonColors}
hover:shadow-lg transition duration-300 ease-in-out
`}
onClick={() => { params.functionToExecute(); setIsDialogOpen(false) }}>
{params.confirmationButtonText}
</div>
</div>
</div>
</div>
</DialogContent>
</Dialog.Portal>
</Dialog.Root>
)
};
const overlayShow = keyframes({
'0%': { opacity: 0 },
'100%': { opacity: 1 },
});
const overlayClose = keyframes({
'0%': { opacity: 1 },
'100%': { opacity: 0 },
});
const contentShow = keyframes({
'0%': { opacity: 0, transform: 'translate(-50%, -50%) scale(.96)' },
'100%': { opacity: 1, transform: 'translate(-50%, -50%) scale(1)' },
});
const contentClose = keyframes({
'0%': { opacity: 1, transform: 'translate(-50%, -50%) scale(1)' },
'100%': { opacity: 0, transform: 'translate(-50%, -52%) scale(.96)' },
});
const DialogOverlay = styled(Dialog.Overlay, {
backgroundColor: blackA.blackA9,
position: 'fixed',
zIndex: 500,
inset: 0,
animation: `${overlayShow} 150ms cubic-bezier(0.16, 1, 0.3, 1)`,
'&[data-state="closed"]': {
animation: `${overlayClose} 150ms cubic-bezier(0.16, 1, 0.3, 1)`,
},
});
const DialogContent = styled(Dialog.Content, {
backgroundColor: 'white',
borderRadius: 18,
zIndex: 501,
boxShadow: 'hsl(206 22% 7% / 35%) 0px 10px 38px -10px, hsl(206 22% 7% / 20%) 0px 10px 20px -15px',
position: 'fixed',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
width: 'auto',
minWidth: '500px',
overflow: 'hidden',
height: 'auto',
maxHeight: '85vh',
maxWidth: '600px',
padding: 11,
animation: `${contentShow} 150ms cubic-bezier(0.16, 1, 0.3, 1)`,
'&:focus': { outline: 'none' },
'&[data-state="closed"]': {
animation: `${contentClose} 150ms cubic-bezier(0.16, 1, 0.3, 1)`,
},
transition: "max-height 0.3s ease-out",
});
export default ConfirmationModal;

120
front/package-lock.json generated
View file

@ -197,9 +197,9 @@
}
},
"node_modules/@babel/core/node_modules/semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"bin": {
"semver": "bin/semver.js"
}
@ -280,9 +280,9 @@
}
},
"node_modules/@babel/helper-compilation-targets/node_modules/semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"bin": {
"semver": "bin/semver.js"
}
@ -345,9 +345,9 @@
}
},
"node_modules/@babel/helper-define-polyfill-provider/node_modules/semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"bin": {
"semver": "bin/semver.js"
}
@ -1790,9 +1790,9 @@
}
},
"node_modules/@babel/preset-env/node_modules/semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"bin": {
"semver": "bin/semver.js"
}
@ -4071,9 +4071,9 @@
}
},
"node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"bin": {
"semver": "bin/semver.js"
}
@ -4950,9 +4950,9 @@
}
},
"node_modules/eslint-plugin-jsx-a11y/node_modules/semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"dev": true,
"bin": {
"semver": "bin/semver.js"
@ -5028,9 +5028,9 @@
}
},
"node_modules/eslint-plugin-react/node_modules/semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"dev": true,
"bin": {
"semver": "bin/semver.js"
@ -6275,9 +6275,9 @@
}
},
"node_modules/make-dir/node_modules/semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"version": "5.7.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
"integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
"bin": {
"semver": "bin/semver"
}
@ -7529,9 +7529,9 @@
}
},
"node_modules/semver": {
"version": "7.3.8",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
"integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
"version": "7.5.4",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
"dev": true,
"dependencies": {
"lru-cache": "^6.0.0"
@ -8427,9 +8427,9 @@
}
},
"node_modules/word-wrap": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
"integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
"integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
"dev": true,
"engines": {
"node": ">=0.10.0"
@ -8709,9 +8709,9 @@
"integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="
},
"semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="
}
}
},
@ -8775,9 +8775,9 @@
}
},
"semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="
},
"yallist": {
"version": "3.1.1",
@ -8824,9 +8824,9 @@
},
"dependencies": {
"semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="
}
}
},
@ -9780,9 +9780,9 @@
},
"dependencies": {
"semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="
}
}
},
@ -11400,9 +11400,9 @@
},
"dependencies": {
"semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="
}
}
},
@ -12037,9 +12037,9 @@
},
"dependencies": {
"semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"dev": true
}
}
@ -12087,9 +12087,9 @@
}
},
"semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"dev": true
}
}
@ -13007,9 +13007,9 @@
},
"dependencies": {
"semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
"version": "5.7.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
"integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g=="
}
}
},
@ -13869,9 +13869,9 @@
}
},
"semver": {
"version": "7.3.8",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
"integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
"version": "7.5.4",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
"dev": true,
"requires": {
"lru-cache": "^6.0.0"
@ -14484,9 +14484,9 @@
}
},
"word-wrap": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
"integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
"integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
"dev": true
},
"wrappy": {