mirror of
https://github.com/fleetdm/fleet
synced 2026-04-21 13:37:30 +00:00
Fleet Calendar feature: Updates to manage automations modal (#17652)
This commit is contained in:
parent
d97e32fc21
commit
4db06f2cbb
16 changed files with 185 additions and 291 deletions
|
|
@ -41,7 +41,7 @@ import TableDataError from "components/DataError";
|
|||
import MainContent from "components/MainContent";
|
||||
|
||||
import PoliciesTable from "./components/PoliciesTable";
|
||||
import ManagePolicyAutomationsModal from "./components/ManagePolicyAutomationsModal";
|
||||
import OtherWorkflowsModal from "./components/OtherWorkflowsModal";
|
||||
import AddPolicyModal from "./components/AddPolicyModal";
|
||||
import DeletePolicyModal from "./components/DeletePolicyModal";
|
||||
|
||||
|
|
@ -129,7 +129,6 @@ const ManagePolicyPage = ({
|
|||
const [showManageAutomationsModal, setShowManageAutomationsModal] = useState(
|
||||
false
|
||||
);
|
||||
const [showPreviewPayloadModal, setShowPreviewPayloadModal] = useState(false);
|
||||
const [showAddPolicyModal, setShowAddPolicyModal] = useState(false);
|
||||
const [showDeletePolicyModal, setShowDeletePolicyModal] = useState(false);
|
||||
|
||||
|
|
@ -477,10 +476,6 @@ const ManagePolicyPage = ({
|
|||
const toggleManageAutomationsModal = () =>
|
||||
setShowManageAutomationsModal(!showManageAutomationsModal);
|
||||
|
||||
const togglePreviewPayloadModal = useCallback(() => {
|
||||
setShowPreviewPayloadModal(!showPreviewPayloadModal);
|
||||
}, [setShowPreviewPayloadModal, showPreviewPayloadModal]);
|
||||
|
||||
const toggleAddPolicyModal = () => setShowAddPolicyModal(!showAddPolicyModal);
|
||||
|
||||
const toggleDeletePolicyModal = () =>
|
||||
|
|
@ -796,15 +791,13 @@ const ManagePolicyPage = ({
|
|||
</div>
|
||||
)}
|
||||
{config && automationsConfig && showManageAutomationsModal && (
|
||||
<ManagePolicyAutomationsModal
|
||||
<OtherWorkflowsModal
|
||||
automationsConfig={automationsConfig}
|
||||
availableIntegrations={config.integrations}
|
||||
availablePolicies={availablePoliciesForAutomation}
|
||||
isUpdatingAutomations={isUpdatingAutomations}
|
||||
showPreviewPayloadModal={showPreviewPayloadModal}
|
||||
onExit={toggleManageAutomationsModal}
|
||||
handleSubmit={handleUpdateAutomations}
|
||||
togglePreviewPayloadModal={togglePreviewPayloadModal}
|
||||
/>
|
||||
)}
|
||||
{showAddPolicyModal && (
|
||||
|
|
|
|||
|
|
@ -0,0 +1,64 @@
|
|||
import React, { useContext } from "react";
|
||||
import { syntaxHighlight } from "utilities/helpers";
|
||||
|
||||
import { AppContext } from "context/app";
|
||||
import { IPolicyWebhookPreviewPayload } from "interfaces/policy";
|
||||
|
||||
const baseClass = "example-payload";
|
||||
|
||||
interface IHostPreview {
|
||||
id: number;
|
||||
display_name: string;
|
||||
url: string;
|
||||
}
|
||||
|
||||
interface IExamplePayload {
|
||||
timestamp: string;
|
||||
policy: IPolicyWebhookPreviewPayload;
|
||||
hosts: IHostPreview[];
|
||||
}
|
||||
|
||||
const ExamplePayload = (): JSX.Element => {
|
||||
const { isFreeTier } = useContext(AppContext);
|
||||
|
||||
const json: IExamplePayload = {
|
||||
timestamp: "0000-00-00T00:00:00Z",
|
||||
policy: {
|
||||
id: 1,
|
||||
name: "Is Gatekeeper enabled?",
|
||||
query: "SELECT 1 FROM gatekeeper WHERE assessments_enabled = 1;",
|
||||
description: "Checks if gatekeeper is enabled on macOS devices.",
|
||||
author_id: 1,
|
||||
author_name: "John",
|
||||
author_email: "john@example.com",
|
||||
resolution: "Turn on Gatekeeper feature in System Preferences.",
|
||||
passing_host_count: 2000,
|
||||
failing_host_count: 300,
|
||||
critical: false,
|
||||
},
|
||||
hosts: [
|
||||
{
|
||||
id: 1,
|
||||
display_name: "macbook-1",
|
||||
url: "https://fleet.example.com/hosts/1",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
display_name: "macbbook-2",
|
||||
url: "https://fleet.example.com/hosts/2",
|
||||
},
|
||||
],
|
||||
};
|
||||
if (isFreeTier) {
|
||||
delete json.policy.critical;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={baseClass}>
|
||||
<pre>POST https://server.com/example</pre>
|
||||
<pre dangerouslySetInnerHTML={{ __html: syntaxHighlight(json) }} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ExamplePayload;
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
.example-payload {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $pad-large;
|
||||
|
||||
pre {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
export { default } from "./ExamplePayload";
|
||||
|
|
@ -1,28 +1,24 @@
|
|||
import React, { useContext } from "react";
|
||||
|
||||
import { AppContext } from "context/app";
|
||||
import Modal from "components/Modal";
|
||||
import Button from "components/buttons/Button";
|
||||
import CustomLink from "components/CustomLink";
|
||||
|
||||
import { IIntegrationType } from "interfaces/integration";
|
||||
|
||||
import Card from "components/Card";
|
||||
import JiraPreview from "../../../../../../assets/images/jira-policy-automation-preview-400x419@2x.png";
|
||||
import ZendeskPreview from "../../../../../../assets/images/zendesk-policy-automation-preview-400x515@2x.png";
|
||||
import JiraPreviewPremium from "../../../../../../assets/images/jira-policy-automation-preview-premium-400x316@2x.png";
|
||||
import ZendeskPreviewPremium from "../../../../../../assets/images/zendesk-policy-automation-preview-premium-400x483@2x.png";
|
||||
|
||||
const baseClass = "preview-ticket-modal";
|
||||
const baseClass = "example-ticket";
|
||||
|
||||
interface IPreviewTicketModalProps {
|
||||
interface IExampleTicketProps {
|
||||
integrationType?: IIntegrationType;
|
||||
onCancel: () => void;
|
||||
}
|
||||
|
||||
const PreviewTicketModal = ({
|
||||
const ExampleTicket = ({
|
||||
integrationType,
|
||||
onCancel,
|
||||
}: IPreviewTicketModalProps): JSX.Element => {
|
||||
}: IExampleTicketProps): JSX.Element => {
|
||||
const { isPremiumTier } = useContext(AppContext);
|
||||
|
||||
const screenshot =
|
||||
|
|
@ -41,30 +37,10 @@ const PreviewTicketModal = ({
|
|||
);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
title="Example ticket"
|
||||
onExit={onCancel}
|
||||
className={baseClass}
|
||||
width="large"
|
||||
>
|
||||
<div className={`${baseClass}`}>
|
||||
<p className="automations-learn-more">
|
||||
Want to learn more about how automations in Fleet work?{" "}
|
||||
<CustomLink
|
||||
url="https://fleetdm.com/docs/using-fleet/automations"
|
||||
text=" Check out the Fleet documentation"
|
||||
newTab
|
||||
/>
|
||||
</p>
|
||||
<div className={`${baseClass}__example`}>{screenshot}</div>
|
||||
<div className="modal-cta-wrap">
|
||||
<Button onClick={onCancel} variant="brand">
|
||||
Done
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
<Card className={baseClass} color="gray">
|
||||
{screenshot}
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
export default PreviewTicketModal;
|
||||
export default ExampleTicket;
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
.example-ticket {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
|
||||
&__screenshot {
|
||||
max-width: 400px;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
export { default } from "./ExampleTicket";
|
||||
|
|
@ -1 +0,0 @@
|
|||
export { default } from "./ManagePolicyAutomationsModal";
|
||||
|
|
@ -19,22 +19,21 @@ import Dropdown from "components/forms/fields/Dropdown";
|
|||
import InputField from "components/forms/fields/InputField";
|
||||
import Radio from "components/forms/fields/Radio";
|
||||
import validUrl from "components/forms/validators/valid_url";
|
||||
import RevealButton from "components/buttons/RevealButton";
|
||||
import CustomLink from "components/CustomLink";
|
||||
import ExampleTicket from "../ExampleTicket";
|
||||
import ExamplePayload from "../ExamplePayload";
|
||||
|
||||
import PreviewPayloadModal from "../PreviewPayloadModal";
|
||||
import PreviewTicketModal from "../PreviewTicketModal";
|
||||
|
||||
interface IManagePolicyAutomationsModalProps {
|
||||
interface IOtherWorkflowsModalProps {
|
||||
automationsConfig: IAutomationsConfig | ITeamAutomationsConfig;
|
||||
availableIntegrations: IIntegrations;
|
||||
availablePolicies: IPolicy[];
|
||||
isUpdatingAutomations: boolean;
|
||||
showPreviewPayloadModal: boolean;
|
||||
onExit: () => void;
|
||||
handleSubmit: (formData: {
|
||||
webhook_settings: Pick<IWebhookSettings, "failing_policies_webhook">;
|
||||
integrations: IIntegrations;
|
||||
}) => void;
|
||||
togglePreviewPayloadModal: () => void;
|
||||
}
|
||||
|
||||
interface ICheckedPolicy {
|
||||
|
|
@ -83,18 +82,16 @@ const useCheckboxListStateManagement = (
|
|||
return { policyItems, updatePolicyItems };
|
||||
};
|
||||
|
||||
const baseClass = "manage-policy-automations-modal";
|
||||
const baseClass = "other-workflows-modal";
|
||||
|
||||
const ManagePolicyAutomationsModal = ({
|
||||
const OtherWorkflowsModal = ({
|
||||
automationsConfig,
|
||||
availableIntegrations,
|
||||
availablePolicies,
|
||||
isUpdatingAutomations,
|
||||
showPreviewPayloadModal,
|
||||
onExit,
|
||||
handleSubmit,
|
||||
togglePreviewPayloadModal: togglePreviewModal,
|
||||
}: IManagePolicyAutomationsModalProps): JSX.Element => {
|
||||
}: IOtherWorkflowsModalProps): JSX.Element => {
|
||||
const {
|
||||
webhook_settings: { failing_policies_webhook: webhook },
|
||||
} = automationsConfig;
|
||||
|
|
@ -131,6 +128,9 @@ const ManagePolicyAutomationsModal = ({
|
|||
IIntegration | undefined
|
||||
>(serverEnabledIntegration);
|
||||
|
||||
const [showExamplePayload, setShowExamplePayload] = useState(false);
|
||||
const [showExampleTicket, setShowExampleTicket] = useState(false);
|
||||
|
||||
const [errors, setErrors] = useState<{ [key: string]: string }>({});
|
||||
|
||||
const { policyItems, updatePolicyItems } = useCheckboxListStateManagement(
|
||||
|
|
@ -218,13 +218,6 @@ const ManagePolicyAutomationsModal = ({
|
|||
z.group_id === selectedIntegration?.group_id,
|
||||
})) || null;
|
||||
|
||||
// if (
|
||||
// !isPolicyAutomationsEnabled ||
|
||||
// (!isWebhookEnabled && !selectedIntegration)
|
||||
// ) {
|
||||
// newPolicyIds = [];
|
||||
// }
|
||||
|
||||
const updatedEnabledPoliciesAcrossPages = () => {
|
||||
if (webhook.policy_ids) {
|
||||
// Array of policy ids on the page
|
||||
|
|
@ -297,34 +290,52 @@ const ManagePolicyAutomationsModal = ({
|
|||
placeholder="https://server.com/example"
|
||||
tooltip="Provide a URL to deliver a webhook request to."
|
||||
/>
|
||||
<Button type="button" variant="text-link" onClick={togglePreviewModal}>
|
||||
Preview payload
|
||||
</Button>
|
||||
<RevealButton
|
||||
isShowing={showExamplePayload}
|
||||
className={baseClass}
|
||||
hideText="Hide example payload"
|
||||
showText="Show example payload"
|
||||
caretPosition="after"
|
||||
onClick={() => setShowExamplePayload(!showExamplePayload)}
|
||||
/>
|
||||
{showExamplePayload && <ExamplePayload />}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const renderIntegrations = () => {
|
||||
return jira?.length || zendesk?.length ? (
|
||||
<div className={`${baseClass}__integrations`}>
|
||||
<Dropdown
|
||||
options={dropdownOptions}
|
||||
onChange={onSelectIntegration}
|
||||
placeholder="Select integration"
|
||||
value={
|
||||
selectedIntegration?.group_id || selectedIntegration?.project_key
|
||||
}
|
||||
label="Integration"
|
||||
error={errors.integration}
|
||||
wrapperClassName={`${baseClass}__form-field ${baseClass}__form-field--frequency`}
|
||||
hint={
|
||||
"For each policy, Fleet will create a ticket with a list of the failing hosts."
|
||||
}
|
||||
<>
|
||||
<div className={`${baseClass}__integrations`}>
|
||||
<Dropdown
|
||||
options={dropdownOptions}
|
||||
onChange={onSelectIntegration}
|
||||
placeholder="Select integration"
|
||||
value={
|
||||
selectedIntegration?.group_id || selectedIntegration?.project_key
|
||||
}
|
||||
label="Integration"
|
||||
error={errors.integration}
|
||||
wrapperClassName={`${baseClass}__form-field ${baseClass}__form-field--frequency`}
|
||||
hint={
|
||||
"For each policy, Fleet will create a ticket with a list of the failing hosts."
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<RevealButton
|
||||
isShowing={showExampleTicket}
|
||||
className={baseClass}
|
||||
hideText={"Hide example ticket"}
|
||||
showText={"Show example ticket"}
|
||||
caretPosition="after"
|
||||
onClick={() => setShowExampleTicket(!showExampleTicket)}
|
||||
/>
|
||||
<Button type="button" variant="text-link" onClick={togglePreviewModal}>
|
||||
Preview ticket
|
||||
</Button>
|
||||
</div>
|
||||
{showExampleTicket && (
|
||||
<ExampleTicket
|
||||
integrationType={getIntegrationType(selectedIntegration)}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<div className={`form-field ${baseClass}__no-integrations`}>
|
||||
<div className="form-field__label">You have no integrations.</div>
|
||||
|
|
@ -338,22 +349,10 @@ const ManagePolicyAutomationsModal = ({
|
|||
);
|
||||
};
|
||||
|
||||
const renderPreview = () =>
|
||||
!isWebhookEnabled ? (
|
||||
<PreviewTicketModal
|
||||
integrationType={getIntegrationType(selectedIntegration)}
|
||||
onCancel={togglePreviewModal}
|
||||
/>
|
||||
) : (
|
||||
<PreviewPayloadModal onCancel={togglePreviewModal} />
|
||||
);
|
||||
|
||||
return showPreviewPayloadModal ? (
|
||||
renderPreview()
|
||||
) : (
|
||||
return (
|
||||
<Modal
|
||||
onExit={onExit}
|
||||
title="Manage automations"
|
||||
title="Other workflows"
|
||||
className={baseClass}
|
||||
width="large"
|
||||
>
|
||||
|
|
@ -372,12 +371,32 @@ const ManagePolicyAutomationsModal = ({
|
|||
isPolicyAutomationsEnabled ? "enabled" : "disabled"
|
||||
}`}
|
||||
>
|
||||
<div className={`form-field ${baseClass}__workflow`}>
|
||||
<div className="form-field__label">Workflow</div>
|
||||
<Radio
|
||||
className={`${baseClass}__radio-input`}
|
||||
label="Ticket"
|
||||
id="ticket-radio-btn"
|
||||
checked={!isWebhookEnabled}
|
||||
value="ticket"
|
||||
name="ticket"
|
||||
onChange={onChangeRadio}
|
||||
/>
|
||||
<Radio
|
||||
className={`${baseClass}__radio-input`}
|
||||
label="Webhook"
|
||||
id="webhook-radio-btn"
|
||||
checked={isWebhookEnabled}
|
||||
value="webhook"
|
||||
name="webhook"
|
||||
onChange={onChangeRadio}
|
||||
/>
|
||||
</div>
|
||||
{isWebhookEnabled ? renderWebhook() : renderIntegrations()}
|
||||
<div className="form-field">
|
||||
{availablePolicies?.length ? (
|
||||
<>
|
||||
<div className="form-field__label">
|
||||
Choose which policies you would like to listen to:
|
||||
</div>
|
||||
<div className="form-field__label">Policies:</div>
|
||||
{policyItems &&
|
||||
policyItems.map((policyItem) => {
|
||||
const { isChecked, name, id } = policyItem;
|
||||
|
|
@ -405,28 +424,14 @@ const ManagePolicyAutomationsModal = ({
|
|||
</>
|
||||
)}
|
||||
</div>
|
||||
<div className={`form-field ${baseClass}__workflow`}>
|
||||
<div className="form-field__label">Workflow</div>
|
||||
<Radio
|
||||
className={`${baseClass}__radio-input`}
|
||||
label="Ticket"
|
||||
id="ticket-radio-btn"
|
||||
checked={!isWebhookEnabled}
|
||||
value="ticket"
|
||||
name="ticket"
|
||||
onChange={onChangeRadio}
|
||||
<p className={`${baseClass}__help-text`}>
|
||||
The workflow will be triggered when hosts fail these policies.{" "}
|
||||
<CustomLink
|
||||
url="https://www.fleetdm.com/learn-more-about/policy-automations"
|
||||
text="Learn more"
|
||||
newTab
|
||||
/>
|
||||
<Radio
|
||||
className={`${baseClass}__radio-input`}
|
||||
label="Webhook"
|
||||
id="webhook-radio-btn"
|
||||
checked={isWebhookEnabled}
|
||||
value="webhook"
|
||||
name="webhook"
|
||||
onChange={onChangeRadio}
|
||||
/>
|
||||
</div>
|
||||
{isWebhookEnabled ? renderWebhook() : renderIntegrations()}
|
||||
</p>
|
||||
</div>
|
||||
<div className="modal-cta-wrap">
|
||||
<Button
|
||||
|
|
@ -447,4 +452,4 @@ const ManagePolicyAutomationsModal = ({
|
|||
);
|
||||
};
|
||||
|
||||
export default ManagePolicyAutomationsModal;
|
||||
export default OtherWorkflowsModal;
|
||||
|
|
@ -1,12 +1,9 @@
|
|||
.manage-policy-automations-modal {
|
||||
.other-workflows-modal {
|
||||
pre,
|
||||
code {
|
||||
background-color: $ui-off-white;
|
||||
color: $core-fleet-blue;
|
||||
border: 1px solid $ui-fleet-black-10;
|
||||
border-radius: $border-radius;
|
||||
padding: 7px $pad-medium;
|
||||
margin: $pad-large 0 0 44px;
|
||||
}
|
||||
|
||||
&__error {
|
||||
|
|
@ -22,4 +19,8 @@
|
|||
&__no-integrations a {
|
||||
display: block;
|
||||
}
|
||||
|
||||
&__help-text {
|
||||
@include help-text;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
export { default } from "./OtherWorkflowsModal";
|
||||
|
|
@ -1,97 +0,0 @@
|
|||
import React, { useContext } from "react";
|
||||
import { syntaxHighlight } from "utilities/helpers";
|
||||
|
||||
import Modal from "components/Modal";
|
||||
import Button from "components/buttons/Button";
|
||||
import CustomLink from "components/CustomLink";
|
||||
import { AppContext } from "context/app";
|
||||
import { IPolicyWebhookPreviewPayload } from "interfaces/policy";
|
||||
|
||||
const baseClass = "preview-data-modal";
|
||||
|
||||
interface IPreviewPayloadModalProps {
|
||||
onCancel: () => void;
|
||||
}
|
||||
|
||||
interface IHostPreview {
|
||||
id: number;
|
||||
display_name: string;
|
||||
url: string;
|
||||
}
|
||||
|
||||
interface IPreviewPayload {
|
||||
timestamp: string;
|
||||
policy: IPolicyWebhookPreviewPayload;
|
||||
hosts: IHostPreview[];
|
||||
}
|
||||
|
||||
const PreviewPayloadModal = ({
|
||||
onCancel,
|
||||
}: IPreviewPayloadModalProps): JSX.Element => {
|
||||
const { isFreeTier } = useContext(AppContext);
|
||||
|
||||
const json: IPreviewPayload = {
|
||||
timestamp: "0000-00-00T00:00:00Z",
|
||||
policy: {
|
||||
id: 1,
|
||||
name: "Is Gatekeeper enabled?",
|
||||
query: "SELECT 1 FROM gatekeeper WHERE assessments_enabled = 1;",
|
||||
description: "Checks if gatekeeper is enabled on macOS devices.",
|
||||
author_id: 1,
|
||||
author_name: "John",
|
||||
author_email: "john@example.com",
|
||||
resolution: "Turn on Gatekeeper feature in System Preferences.",
|
||||
passing_host_count: 2000,
|
||||
failing_host_count: 300,
|
||||
critical: false,
|
||||
},
|
||||
hosts: [
|
||||
{
|
||||
id: 1,
|
||||
display_name: "macbook-1",
|
||||
url: "https://fleet.example.com/hosts/1",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
display_name: "macbbook-2",
|
||||
url: "https://fleet.example.com/hosts/2",
|
||||
},
|
||||
],
|
||||
};
|
||||
if (isFreeTier) {
|
||||
delete json.policy.critical;
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal
|
||||
title="Example payload"
|
||||
onExit={onCancel}
|
||||
onEnter={onCancel}
|
||||
className={baseClass}
|
||||
>
|
||||
<div className={`${baseClass}__preview-modal`}>
|
||||
<p>
|
||||
Want to learn more about how automations in Fleet work?{" "}
|
||||
<CustomLink
|
||||
url="https://fleetdm.com/docs/using-fleet/automations"
|
||||
text="Check out the Fleet documentation"
|
||||
newTab
|
||||
/>
|
||||
</p>
|
||||
<div className={`${baseClass}__payload-request-preview`}>
|
||||
<pre>POST https://server.com/example</pre>
|
||||
</div>
|
||||
<div className={`${baseClass}__payload-webhook-preview`}>
|
||||
<pre dangerouslySetInnerHTML={{ __html: syntaxHighlight(json) }} />
|
||||
</div>
|
||||
<div className="modal-cta-wrap">
|
||||
<Button onClick={onCancel} variant="brand">
|
||||
Done
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default PreviewPayloadModal;
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
.preview-payload-modal {
|
||||
&__sandbox-info {
|
||||
margin-top: $pad-medium;
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
margin-bottom: $pad-medium;
|
||||
}
|
||||
|
||||
p:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&__info-header {
|
||||
font-weight: $bold;
|
||||
}
|
||||
|
||||
&__advanced-options-button {
|
||||
margin: $pad-medium 0;
|
||||
color: $core-vibrant-blue;
|
||||
font-weight: $bold;
|
||||
font-size: $x-small;
|
||||
}
|
||||
|
||||
.downcaret {
|
||||
&::after {
|
||||
content: url("../assets/images/icon-chevron-blue-16x16@2x.png");
|
||||
transform: scale(0.5);
|
||||
width: 16px;
|
||||
border-radius: 0px;
|
||||
padding: 0px;
|
||||
padding-left: 2px;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
.upcaret {
|
||||
&::after {
|
||||
content: url("../assets/images/icon-chevron-blue-16x16@2x.png");
|
||||
transform: scale(0.5) rotate(180deg);
|
||||
width: 16px;
|
||||
border-radius: 0px;
|
||||
padding: 0px;
|
||||
padding-left: 2px;
|
||||
margin-bottom: 4px;
|
||||
margin-left: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.Select-value-label {
|
||||
font-size: $small;
|
||||
}
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
export { default } from "./PreviewPayloadModal";
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
.preview-ticket-modal {
|
||||
&__example {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
&__screenshot {
|
||||
width: 400px;
|
||||
height: auto;
|
||||
border-radius: 8px;
|
||||
filter: drop-shadow(0px 4px 16px rgba(0, 0, 0, 0.1));
|
||||
}
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
export { default } from "./PreviewTicketModal";
|
||||
Loading…
Reference in a new issue