import React, { useCallback, useContext, useState } from "react"; import { InjectedRouter } from "react-router"; import { Location } from "history"; import { AppContext } from "context/app"; import PATHS from "router/paths"; import { getPathWithQueryParams } from "utilities/url"; import { ICreateQueryRequestBody } from "interfaces/schedulable_query"; import queryAPI from "services/entities/queries"; import { NotificationContext } from "context/notification"; import { getErrorReason } from "interfaces/errors"; import { INVALID_PLATFORMS_FLASH_MESSAGE, INVALID_PLATFORMS_REASON, } from "utilities/constants"; import { API_ALL_TEAMS_ID, APP_CONTEXT_ALL_TEAMS_ID, ITeamSummary, } from "interfaces/team"; import Modal from "components/Modal"; import Button from "components/buttons/Button"; import InputField from "components/forms/fields/InputField"; import TeamsDropdown from "components/TeamsDropdown"; import { useTeamIdParam } from "hooks/useTeamIdParam"; const baseClass = "save-as-new-query-modal"; interface ISaveAsNewQueryModal { router: InjectedRouter; location: Location; initialQueryData: ICreateQueryRequestBody; hostId?: number; onExit: () => void; } interface ISANQFormData { queryName: string; team: Partial; } interface ISANQFormErrors { queryName?: string; team?: string; } const validateFormData = (formData: ISANQFormData): ISANQFormErrors => { const errors: ISANQFormErrors = {}; if (!formData.queryName || formData.queryName.trim() === "") { errors.queryName = "Name must be present"; } return errors; }; const SaveAsNewQueryModal = ({ router, location, initialQueryData, hostId, onExit, }: ISaveAsNewQueryModal) => { const { renderFlash } = useContext(NotificationContext); const { isPremiumTier } = useContext(AppContext); const [formData, setFormData] = useState({ queryName: `Copy of ${initialQueryData.name}`, team: { id: initialQueryData.fleet_id, name: undefined, }, }); const [isSaving, setIsSaving] = useState(false); const [formErrors, setFormErrors] = useState({}); const { userTeams } = useTeamIdParam({ router, location, includeAllTeams: true, includeNoTeam: false, permittedAccessByTeamRole: { admin: true, maintainer: true, observer: false, observer_plus: false, technician: false, }, }); const onInputChange = useCallback( ({ name, value, }: { name: string; value: string | Partial; }) => { const newFormData = { ...formData, [name]: value }; setFormData(newFormData); const newErrors = validateFormData(newFormData); const errsToSet: ISANQFormErrors = {}; Object.keys(formErrors).forEach((k) => { if (k in newErrors) { errsToSet[k as keyof ISANQFormErrors] = newErrors[k as keyof ISANQFormErrors]; } }); setFormErrors(errsToSet); }, [formData, formErrors] ); const onInputBlur = () => { setFormErrors(validateFormData(formData)); }; const onTeamChange = useCallback( (teamId: number) => { const selectedTeam = userTeams?.find((team) => team.id === teamId); setFormData((prevData) => ({ ...prevData, team: { id: teamId, name: selectedTeam ? selectedTeam.name : undefined, }, })); }, [userTeams] ); // take all existing data for query from parent, allow editing name and team const handleSave = async (evt: React.FormEvent) => { evt.preventDefault(); const errors = validateFormData(formData); if (Object.keys(errors).length > 0) { setFormErrors(errors); return; } setIsSaving(true); const { queryName, team: { id: teamId, name: teamName }, } = formData; const createBody = { ...initialQueryData, name: queryName, fleet_id: teamId === APP_CONTEXT_ALL_TEAMS_ID ? API_ALL_TEAMS_ID : teamId, }; try { const { query: newQuery } = await queryAPI.create(createBody); setIsSaving(false); renderFlash("success", `Successfully added report ${newQuery.name}.`); router.push( getPathWithQueryParams(PATHS.REPORT_DETAILS(newQuery.id), { fleet_id: newQuery.team_id, host_id: hostId, }) ); } catch (createError: unknown) { let errFlash = "Could not create report. Please try again."; const reason = getErrorReason(createError); if (reason.includes("already exists")) { let teamText; if (teamId !== APP_CONTEXT_ALL_TEAMS_ID) { teamText = teamName ? `the ${teamName} fleet` : "this fleet"; } else { teamText = "all fleets"; } errFlash = `A report called "${queryName}" already exists for ${teamText}.`; } else if (reason.includes(INVALID_PLATFORMS_REASON)) { errFlash = INVALID_PLATFORMS_FLASH_MESSAGE; } setIsSaving(false); renderFlash("error", errFlash); } }; return (
{isPremiumTier && (userTeams?.length || 0) > 1 && (
Fleet
)}
); }; export default SaveAsNewQueryModal;